﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Pda_Total_Station
{
    public class svpoint
    {
        public string name;
        public double E;
        public double H;
        public double N;
        public double Hz;
        public double Hv;
        public double slope;
        public double Hz1;
        public double Hv1;
        public double slope1;
        public double Hz2;
        public double Hv2;
        public double slope2;
        public double dert;//指标差
        public double FH; //最终的H坐标
        public bool check = false;

        public DateTime time;
        public svpoint()
        { }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="na">点名</param>
        /// <param name="e">东坐标</param>
        /// <param name="n">北坐标</param>
        /// <param name="h">高程</param>
        public svpoint(string na, double e, double n, double h)
        {
            name = na;
            E = e;
            N = n;
            H = h;
        }
    }
    public enum Face
    {
        face1,
        face2
    }
    public class svtps
    {
        //配置好的观测数据
        public List<svpoint> points;
        public svpoint center;
        public double heigt;
        public Face curface = Face.face1;
        double PI = 3.1415926535898;
        public turns myturn;
        public svtps()
        {
            myturn = new turns();
        }
        //构造函数
        public svtps(List<svpoint> pts , svpoint instrucenter,double instruheight)
        {
            points = pts;
            center = instrucenter;
            heigt = instruheight;
        }
        public svtps(svpoint instrucenter, double instruheight)
        {
            myturn = new turns();
            center = instrucenter;
            heigt = instruheight;
        }
        //正镜展点到xyz坐标
        public svpoint PolarToXYZ(double az, double hv, double slope)
        {
            if (curface == Face.face1)
            {
                hv = PI / 2 - hv;
            }
            else
            {
                hv = PI / 2 - (2 * PI - hv);
            }
            double dist = slope * Math.Cos(hv);
            double K = 0.13;
            svpoint point = new svpoint("", center.E + dist * Math.Sin(az), center.N + dist * Math.Cos(az),
                center.H + dist * Math.Sin(hv) + dist * dist * (1 - K) / 2 / 6378000);
            return point;
        }
        //求出高度
        public double get_height(double hv, double slope)
        {
           
            if (curface == Face.face2)
            {
                hv = PI / 2 - (2 * PI - hv);
            }
            else
            {
                hv = PI / 2 - hv;
            }
            double K = 0.13;
            double dist = slope * Math.Cos(hv);
            return center.H + dist * Math.Sin(hv) + dist * dist * (1 - K) / 2 / 6378000;    
        }
        public double get_height(double hv, double slope, Face f)
        {
            if (slope == 0)
            {
                return 0;
            }
            if (f == Face.face2)
            {
                hv = PI / 2 - (2 * PI - hv);
            }
            else
            {
                hv = PI / 2 - hv;
            }
            double K = 0.13;
            double dist = slope * Math.Cos(hv);
            return center.H + dist * Math.Sin(hv) + dist * dist * (1 - K) / 2 / 6378000;
        }

        public double get_height1(double real_hv, double slope)
        {
            double K = 0.13;
            double dist = slope * Math.Cos(real_hv);
            return center.H + dist * Math.Sin(real_hv) + dist * dist * (1 - K) / 2 / 6378000;    
        }
        //获取水平角
        public double getAzim(int i)
        {
            vector v = new vector(center, points[i]);
            double angle = v.Azimuth;
            if (curface == Face.face2)
            {
                angle += Math.PI;
                if (angle > PI * 2)
                {
                    angle -= 2 * PI;
                }
            }
            return angle;
        }

        public double getVertA(int i)
        {
            vector v = new vector(center, points[i]);
            double angle = Math.PI / 2 - v.VertcalAngle;
            if (curface == Face.face2)
            {
                angle = PI * 2 - angle;
            }
            return angle;
        }
        public void get_value()
        {
            for (int i = 0; i < myturn.turn_list.Count; i++)
            {
                for (int j = points.Count - 1; j >= 0; j--)
                {
                    if (myturn.turn_list[i].pts[j].slope1 != 0 && myturn.turn_list[i].pts[j].slope2 != 0)
                    {
                        myturn.turn_list[i].pts[j].H = get_height(myturn.turn_list[i].pts[j].Hv1, myturn.turn_list[i].pts[j].slope1, Face.face1)
                                              + get_height(myturn.turn_list[i].pts[j].Hv2, myturn.turn_list[i].pts[j].slope2, Face.face2);
                        myturn.turn_list[i].pts[j].H = myturn.turn_list[i].pts[j].H / 2;
                    }
                    else if (myturn.turn_list[i].pts[j].slope1 == 0 && myturn.turn_list[i].pts[j].slope2 == 0)//如果都为0,表示没测到,删掉.
                    {
                        myturn.turn_list[i].pts.RemoveAt(j);
                    }
                    else if (myturn.turn_list[i].pts[j].slope2 == 0)
                    {
                        myturn.turn_list[i].pts[j].H = get_height(myturn.turn_list[i].pts[j].Hv1, myturn.turn_list[i].pts[j].slope1, Face.face1);
                    }
                    else
                    {
                        myturn.turn_list[i].pts[j].H = get_height(myturn.turn_list[i].pts[j].Hv2, myturn.turn_list[i].pts[j].slope2, Face.face2);
                    }
                }
            }
            for (int i = 0; i< points.Count; i++)
            {
                double h = 0;
                for (int j = 0; j < myturn.turn_list.Count; j++)
                {
                    h = h + myturn.turn_list[j].pts[i].H;
                }
                h = h / myturn.Count;
                myturn.turn_list[0].pts[i].H = Math.Round(h, 4);
            }
        }
    }

    public class vector
    {
        public double de;
        public double dn;
        public double dh;
        double PI = 3.1415926535898;
        public vector(svpoint p1, svpoint p2)
        {
            de = p2.E - p1.E;
            dn = p2.N - p1.N;
            dh = p2.H - p1.H;
        }
        public double  Azimuth 
        { 
            get
            {
                return PI / 2 * (2 - Math.Sign(de + 1.0E-30)) - Math.Atan(dn / (de + 1.0E-30));
            }
            
        }
        public double VertcalAngle
        {
            get
            {
                return Math.Atan(dh / (Distance + 1.0E-30));
            }
        }
        public double Distance
        {
            get
            {
                return Math.Sqrt(de * de + dn * dn);
            }
        }


    }

    public class turn
    {
        double PI = 3.1415926535898;
        public List<svpoint> pts;
        public turn()
        {
            pts = new List<svpoint>();
        }
        public turn(int count)
        {
            pts = new List<svpoint>(count);
        }
        public bool check(ref string msg)
        {
            bool pass = true;
            for (int i = 0; i < pts.Count; i++)
            {
                double dhv ;
                if (pts[i].slope1 != 0 && pts[i].slope2 != 0)
                {
                    dhv = (pts[i].Hv1 + pts[i].Hv2 - 2 * PI);
                    pts[i].dert = dhv;
                    pts[i].Hv = (pts[i].Hv1 + 2 * PI - pts[i].Hv2) / 2;
                    pts[i].slope = (pts[i].slope1 + pts[i].slope2) / 2;
                }
                else
                {
                    dhv = (pts[i].Hv1 == 0) ? (pts[i].Hv2 - 2 * PI) : pts[i].Hv1;
                    pts[i].dert = dhv;
                    pts[i].Hv = (pts[i].Hv1 == 0) ? pts[i].Hv2 : pts[i].Hv1;
                    pts[i].slope = (pts[i].slope1 == 0) ? pts[i].slope2 : pts[i].slope1;
                }

                if (Math.Abs(dhv) > 9 / 206265)
                {
                    msg += pts[i].name + ",";
                    pts[i].check = false;
                    pass =  false;
                }
            }
            msg += "\r\n指标差超限";
            return pass;
        }
    }

    public class turns
    {
        public List<turn> turn_list;
        public int Count
        {
            set
            {
                turn_list = new List<turn>(value);
            }
            get
            {
                return turn_list.Count;
            }
        }
        public bool check(ref string msg)
        {
            int cc = turn_list[0].pts.Count;
            //for (int i = 1; i < Count; i++)
            //{
            //    if (turn_list[i].pts.Count != cc)
            //    {
            //        msg = "第" + (i + 1).ToString() + "测回点数不吻合";
            //        return false;
            //    }
            //}
            for (int i = 0; i < Count; i++)
            {
                for (int j = i + 1; j < Count; j++)
                {
                    for (int k = 0; k < cc; k++)
                    {
                        double dd = Math.Abs(turn_list[i].pts[k].dert - turn_list[j].pts[k].dert);
                        if (dd > 6 / 206265)
                        {
                            msg = "第" + (i + 1).ToString() + "测回与第" + (j + 1).ToString() + "测回指标差超限,\r\n是否重新观测?";
                            return false;
                        }
                    }
                }
            }
            return true;
        }



    }


}
